package org.lex.tf.core;

public class Expression implements Cloneable
{
	private int value = 0;
	private StringBuilder expression = null;
	private int elementsCount = 0;

	public Expression( int value )
	{
		this.value = value;
		this.expression = new StringBuilder();
		this.expression.append( value );
		this.elementsCount++;
	}

	public int getValue()
	{
		return value;
	}

	public Expression add( int v )
	{
		this.value += v;
		this.expression.append( '+' ).append( v );
		this.elementsCount++;
		return this;
	}

	public Expression add( Expression v )
	{
		this.value += v.getValue();
		String bak = this.toString();
		this.expression.setLength( 0 );
		this.expression.append( bak );
		this.expression.append( '+' ).append( v );
		this.elementsCount += v.elementsCount;
		return this;
	}

	public Expression minus( int v )
	{
		this.value -= v;
		this.expression.append( '-' ).append( v );
		this.elementsCount++;
		return this;
	}

	public Expression minus( Expression v )
	{
		this.value -= v.getValue();
		String s = this.toString();
		this.expression.setLength( 0 );
		this.expression.append( s );
		this.expression.append( '-' ).append( v );
		this.elementsCount += v.elementsCount;
		return this;
	}

	public Expression mul( int v )
	{
		this.value *= v;
		String s = this.toString();
		this.expression.setLength( 0 );
		this.expression.append( s );
		this.expression.append( '*' ).append( v );
		this.elementsCount++;
		return this;
	}

	public Expression mul( Expression v )
	{
		this.value *= v.getValue();
		String s = this.toString();
		this.expression.setLength( 0 );
		this.expression.append( s );
		this.expression.append( '*' ).append( v );
		this.elementsCount += v.elementsCount;
		return this;
	}

	public static boolean canDiv( int value, int v )
	{
		if( 0 == v )
			return false;
		return (value >= v) && ((value % v) == 0);
	}

	public Expression div( int v )
	{
		if( 0 == v )
			throw new IllegalArgumentException( "Divide by zero" );
		this.value /= v;
		String s = this.toString();
		this.expression.setLength( 0 );
		this.expression.append( s );
		this.expression.append( '/' ).append( v );
		this.elementsCount++;
		return this;
	}

	public Expression div( Expression v )
	{
		if( 0 == v.getValue() )
			throw new IllegalArgumentException( "Divide by zero" );
		this.value /= v.getValue();
		String s = this.toString();
		this.expression.setLength( 0 );
		this.expression.append( s );
		this.expression.append( '/' ).append( v );
		this.elementsCount += v.elementsCount;
		return this;
	}

	@Override
	public int hashCode()
	{
		final int prime = 31;
		int result = 1;
		result = prime * result + elementsCount;
		result = prime * result + ((expression == null) ? 0 : expression.hashCode());
		result = prime * result + value;
		return result;
	}

	@Override
	public boolean equals( Object obj )
	{
		if( this == obj )
			return true;
		if( obj == null )
			return false;
		if( getClass() != obj.getClass() )
			return false;
		Expression other = (Expression) obj;
		if( elementsCount != other.elementsCount )
			return false;
		if( value != other.value )
			return false;
		int len = this.expression.length();
		if( len != other.expression.length() )
			return false;
		for( int i = 0; i < len; i++ )
			if( this.expression.charAt( i ) != other.expression.charAt( i ) )
				return false;
		return true;
	}

	@Override
	public Expression clone()
	{
		Expression expr = new Expression( 0 );
		expr.elementsCount = this.elementsCount;
		expr.expression = new StringBuilder( this.expression.length() ).append( this.expression );
		expr.value = this.value;
		return expr;
	}

	@Override
	public String toString()
	{
		if( this.elementsCount < 2 )
			return this.expression.toString();
		return '(' + this.expression.toString() + ')';
	}
}
